package ms.jasim.console.gui.component;

import java.awt.Font;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SpringLayout;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.TitledBorder;

import ms.jacrim.framework.MessageOutput;
import ms.jacrim.pddl.PddlSolution;
import ms.jasim.framework.PddlModel;
import ms.jasim.framework.PddlSolutionProvider;
import ms.jasim.framework.SolutionGenerator;
import ms.spm.IAppContext;
import ms.utils.EventListImpl;
import ms.utils.ExceptionUtil;
import ms.utils.NamedList;
import ms.utils.Utils;

public class MP_PlannerPanel extends JPanel implements MessageOutput, PddlSolutionProvider {

	private JButton cmdStopPlanner;
	private JButton cmdStartPlanner;
	private JTextArea txtConsole;
	private SpringLayout springLayout_2;
	private JTextField txtPDDLfile;
	private JTextField txtProcessTime;
	private JTextField txtNoSolution;
	private SpringLayout springLayout_1;
	private SpringLayout springLayout;
	
	private static final long serialVersionUID = 1L;
	
	public IAppContext Context;
	private SolutionGenerator solGenerator;
	public final EventListImpl onPlanning = new EventListImpl();
	public final EventListImpl onPlanned = new EventListImpl();
	/**
	 * Create the panel
	 */
	public MP_PlannerPanel() {
		super();
		
		springLayout = new SpringLayout();
		setLayout(springLayout);

		final JPanel panel = new JPanel();
		springLayout_1 = new SpringLayout();
		panel.setLayout(springLayout_1);
		panel.setBorder(new TitledBorder(null, "Options", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null,
				UIManager.getColor("MenuItem.acceleratorForeground")));
		add(panel);
		springLayout.putConstraint(SpringLayout.EAST, panel, -10, SpringLayout.EAST, this);
		springLayout.putConstraint(SpringLayout.WEST, panel, 5, SpringLayout.WEST, this);

		final JLabel maxOfLabel = new JLabel();
		maxOfLabel.setText("No. of solutions");
		panel.add(maxOfLabel);
		springLayout_1.putConstraint(SpringLayout.EAST, maxOfLabel, 101, SpringLayout.WEST, panel);
		springLayout_1.putConstraint(SpringLayout.WEST, maxOfLabel, 14, SpringLayout.WEST, panel);
		springLayout_1.putConstraint(SpringLayout.NORTH, maxOfLabel, 5, SpringLayout.NORTH, panel);

		final JLabel domainFileLabel_1 = new JLabel();
		domainFileLabel_1.setText("PDDL file");
		panel.add(domainFileLabel_1);
		springLayout_1.putConstraint(SpringLayout.WEST, domainFileLabel_1, 14, SpringLayout.WEST, panel);
		springLayout_1.putConstraint(SpringLayout.NORTH, domainFileLabel_1, 30, SpringLayout.NORTH, panel);

		final JLabel maxProcessingTimeLabel = new JLabel();
		maxProcessingTimeLabel.setText("Processing time");
		panel.add(maxProcessingTimeLabel);
		springLayout_1.putConstraint(SpringLayout.SOUTH, maxProcessingTimeLabel, 19, SpringLayout.NORTH, panel);
		springLayout_1.putConstraint(SpringLayout.NORTH, maxProcessingTimeLabel, 5, SpringLayout.NORTH, panel);
		springLayout_1.putConstraint(SpringLayout.EAST, maxProcessingTimeLabel, 378, SpringLayout.WEST, panel);
		springLayout_1.putConstraint(SpringLayout.WEST, maxProcessingTimeLabel, 282, SpringLayout.WEST, panel);

		txtNoSolution = new JTextField();
		txtNoSolution.setText("3");
		panel.add(txtNoSolution);
		springLayout_1.putConstraint(SpringLayout.NORTH, txtNoSolution, 2, SpringLayout.NORTH, panel);
		springLayout_1.putConstraint(SpringLayout.EAST, txtNoSolution, 276, SpringLayout.WEST, panel);
		springLayout_1.putConstraint(SpringLayout.WEST, txtNoSolution, 115, SpringLayout.WEST, panel);

		txtProcessTime = new JTextField();
		panel.add(txtProcessTime);
		springLayout_1.putConstraint(SpringLayout.EAST, txtProcessTime, -101, SpringLayout.EAST, panel);
		springLayout_1.putConstraint(SpringLayout.WEST, txtProcessTime, 5, SpringLayout.EAST, maxProcessingTimeLabel);
		springLayout_1.putConstraint(SpringLayout.NORTH, txtProcessTime, 2, SpringLayout.NORTH, panel);

		txtPDDLfile = new JTextField();
		txtPDDLfile.setEditable(false);
		panel.add(txtPDDLfile);
		springLayout_1.putConstraint(SpringLayout.EAST, txtPDDLfile, -101, SpringLayout.EAST, panel);
		springLayout_1.putConstraint(SpringLayout.WEST, txtPDDLfile, 0, SpringLayout.WEST, txtNoSolution);
		springLayout_1.putConstraint(SpringLayout.NORTH, txtPDDLfile, 0, SpringLayout.NORTH, domainFileLabel_1);

		final JButton viewButton_1 = new JButton();
		viewButton_1.setMargin(new Insets(0, 2, 0, 2));
		viewButton_1.setText("View");
		panel.add(viewButton_1);
		springLayout_1.putConstraint(SpringLayout.NORTH, viewButton_1, 30, SpringLayout.NORTH, panel);
		springLayout_1.putConstraint(SpringLayout.EAST, viewButton_1, -7, SpringLayout.EAST, panel);
		springLayout_1.putConstraint(SpringLayout.WEST, viewButton_1, -96, SpringLayout.EAST, panel);

		final JPanel panel_1 = new JPanel();
		panel_1.setBorder(new TitledBorder(null, "Planner Output", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null,
				UIManager.getColor("MenuItem.acceleratorForeground")));
		springLayout_2 = new SpringLayout();
		panel_1.setLayout(springLayout_2);
		add(panel_1);
		springLayout.putConstraint(SpringLayout.SOUTH, panel, -5, SpringLayout.NORTH, panel_1);
		springLayout.putConstraint(SpringLayout.NORTH, panel, 5, SpringLayout.NORTH, this);
		springLayout.putConstraint(SpringLayout.SOUTH, panel_1, -11, SpringLayout.SOUTH, this);
		springLayout.putConstraint(SpringLayout.NORTH, panel_1, 115, SpringLayout.NORTH, this);
		springLayout.putConstraint(SpringLayout.EAST, panel_1, 0, SpringLayout.EAST, panel);
		springLayout.putConstraint(SpringLayout.WEST, panel_1, 0, SpringLayout.WEST, panel);

		cmdStartPlanner = new JButton();
		cmdStartPlanner.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				startPlanner();
			}
		});

		cmdStartPlanner.setMargin(new Insets(0, 2, 0, 2));
		cmdStartPlanner.setText("Start Planner");
		panel_1.add(cmdStartPlanner);
		springLayout_2.putConstraint(SpringLayout.EAST, cmdStartPlanner, 105, SpringLayout.WEST, panel_1);
		springLayout_2.putConstraint(SpringLayout.WEST, cmdStartPlanner, 5, SpringLayout.WEST, panel_1);
		springLayout_2.putConstraint(SpringLayout.NORTH, cmdStartPlanner, 3, SpringLayout.NORTH, panel_1);

		final JScrollPane scrollPane = new JScrollPane();
		panel_1.add(scrollPane);
		springLayout_2.putConstraint(SpringLayout.SOUTH, scrollPane, -9, SpringLayout.SOUTH, panel_1);
		springLayout_2.putConstraint(SpringLayout.NORTH, scrollPane, 5, SpringLayout.SOUTH, cmdStartPlanner);
		springLayout_2.putConstraint(SpringLayout.EAST, scrollPane, -7, SpringLayout.EAST, panel_1);
		springLayout_2.putConstraint(SpringLayout.WEST, scrollPane, 0, SpringLayout.WEST, cmdStartPlanner);

		txtConsole = new JTextArea();
		txtConsole.setTabSize(4);
		txtConsole.setOpaque(true);
		txtConsole.setFont(new Font("Courier New", Font.PLAIN, 12));
		txtConsole.setEditable(false);
		scrollPane.setViewportView(txtConsole);

		cmdStopPlanner = new JButton();
		cmdStopPlanner.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				stopPlanner();
			}
		});
		cmdStopPlanner.setMargin(new Insets(0, 2, 0, 2));
		cmdStopPlanner.setText("Stop Planner");
		panel_1.add(cmdStopPlanner);
		springLayout_2.putConstraint(SpringLayout.NORTH, cmdStopPlanner, 3, SpringLayout.NORTH, panel_1);
		springLayout_2.putConstraint(SpringLayout.EAST, cmdStopPlanner, 105, SpringLayout.EAST, cmdStartPlanner);
		springLayout_2.putConstraint(SpringLayout.WEST, cmdStopPlanner, 5, SpringLayout.EAST, cmdStartPlanner);
		//

		setPlanningStatus(false);
	}

	public void setContext(IAppContext context) {
		Context = context.createChildContext("MP_PlannerPanel");
		Context.addService(this);
		try {
			solGenerator = new SolutionGenerator(Context);
			solGenerator.setCompleteListener(new Runnable() {
				@Override
				public void run() {
					setPlanningStatus(false);
					onPlanned.invoke(MP_PlannerPanel.this, null);
				}
			});
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	protected void stopPlanner() {
		if (solGenerator != null)
			solGenerator.stopPlanner();
	}

	protected void startPlanner() {
		try {
			
			txtConsole.setText("");
			
			PddlModel model = Context.getService(PddlModel.class);
			if (model != null)  {
				setPlanningStatus(true);
				onPlanning.invoke(MP_PlannerPanel.this, null);
				solGenerator.startPlanner(model, Utils.parseIntDef(txtNoSolution.getText(), 3), true);
				
			}
		} catch (Exception e) {
			ExceptionUtil.handle(e, Context);
		}
	}

	@Override
	public NamedList<PddlSolution> getSolutions() {
		return solGenerator != null ? solGenerator.getSolutions() : null;
	}
	
	public void setPlanningStatus(boolean planning) {
		txtNoSolution.setEnabled(!planning);
		txtProcessTime.setEnabled(!planning);
		cmdStartPlanner.setEnabled(!planning);
		cmdStopPlanner.setEnabled(planning);
	}
	
	@Override
	public void write(String category, String message) {
		SwingUtilities.invokeLater(new writer(message));
	}

	@Override
	public void write(String category, String format, Object... args) {
		write(null, String.format(format, args));
	}

	private class writer implements Runnable {

		public String msg;
		
		public writer(String msg) {
			this.msg = msg;
		}

		@Override
		public void run() {
			txtConsole.setText(txtConsole.getText() + msg);
		}
	}
}
